#ifndef OPERATORDEFINITION_H
#define OPERATORDEFINITION_H

#include <QObject>
#include <QMap>
#include <QVector>
#include <QRect>
#include <QPoint>

#include <QtCore/QJsonObject>
#include <QtCore/qglobal.h>

#include <QFile>
#include <QtXml>
#include <QDebug>
#include <QDomElement>
#include <QDomDocument>

class QDomNode;
class QDomElement;
class QDomDocument;

#define RSM_DEFINED_EXPORT Q_DECL_EXPORT

//基础操作符中的参数,立即数或引用
struct parameter
{
    bool isImmediate=false;//是否为立即数
    QString value;
    QDomNode node;
};

//结构体变量的元素
typedef struct field
{
    QString name;
    QString type;
    QString oid;
}Field;

//数组变量的元素
typedef struct array
{
    QString type;
    parameter size;
}Array;

//变量
struct Variable
{
    QString id;          //变量id
    QString operatorId;  //操作符id
    QString name;        //变量名
    QString type;        //变量类型
    QString dataType;    //数据类型

    QDomNode node;//变量节点

    bool hasPara=false;//是否包含参数
    bool hasT=false;//是否包含泛型

    //default
    QDomNode defaultNode;
    QString defaultValue;

    //last
    QDomNode lastNode;
    QString lastValue;

    bool isLine=false;//是否为中间变量

    bool isStruct=false;
    bool isArray=false;

    QList<field> fieldList;
    Array array;


    QString comment;   //描述
    QString mnemonic;  //助记符
};

//结构体元素
struct label
{
    QString labelName;
    QString value;
};

//一元操作符
struct UnaryOp
{
    QString constVarRef;
};

//二元操作符
struct BinaryOp
{
    QStringList constVarRefs;
};

//多元操作符
struct NAryOp
{
    QStringList constVarRefs;
};

//Previous操作符
struct PreOp
{
    QStringList flows;
};

//Inin操作符
struct InitOp
{
    QList<parameter> parameters;
    QStringList flows;
};

//Followed By操作符
struct FbyOp
{
    QStringList flows;
    parameter delay;
    QList<parameter> parameters;
};

//Projection操作符
struct PrjOp
{
    QString flow;
    QList<parameter> parameters;
};

//Slice操作符
struct SliceOp
{
    QString array;//输入
    parameter fromIndex;
    parameter toIndex;
};

//Dynamic Projection操作符
struct PrjDynOp
{
    QString array;//输入
    QList<parameter> indexes;
    parameter defaultpara;
};

//DataStructure操作符
struct DataStructOp
{
    QList<label> labels;
};

//ScalarToVector
struct ScalarToVectorOp
{
    QStringList flows;
    parameter size;
};

//DataArray
struct DataArrayOp
{
    QStringList datas;
};

//Assign of a Structrued Element
struct ChgIthOp
{
    QString flow;
    QList<parameter> parameters;
    QString value;
};

//If Then Else
struct IfThenElseOp
{
    QString ifValue;
    QStringList thens;
    QStringList elses;
};

//Case
struct CaseOp
{
    QString switchValue;
    QList<label> cases;
    QString defaultValue;
};

//Make
struct MakeOp
{
    QString typeRef;
    QStringList calls;
};

//Flatten
struct FlattenOp
{
    QString typeRef;
    QString call;
};

//NumericCast
struct NumericCastOp
{
    QString typeRef;
    parameter flow;
};

//Times
struct TimesOp
{
    QString condition;
    parameter counter;
};

//Transpose
struct TransposeOp
{
    QString array;
    parameter dimension1;
    parameter dimension2;
};

//lsl
struct LslOp
{
    QString input;
    parameter number;
};

//lsr
struct LsrOp
{
    QString input;
    parameter number;
};

//ActivateOp
struct ActivateOp
{
    bool isInit;
    QString operatorRef;//内部为组合操作符或自定义操作符
    bool isRef=false;//是否为自定义操作符
    bool isMakeOp=false;
    QString makeRef;//内部为Make操作符
    bool isFlattenOp=false;
    QString flattenRef;//内部为Flatten操作符

    QString every;
    QStringList calls;//输入
    QList<parameter> defaultValue;

    QString usedIdName;
    QString refName;
};

//RestartOp
struct RestartOp
{
    QString operatorRef;//内部为组合操作符或自定义操作符
    bool isRef=false;//是否为自定义操作符
    bool isMakeOp=false;
    QString makeRef;//内部为Make操作符
    bool isFlattenOp=false;
    QString flattenRef;//内部为Flatten操作符

    QString every;
    QStringList calls;//输入

    QString usedIdName;
    QString refName;
};

//Iterator
struct IteratorOp
{
    QString iteratorType;//高阶类型
    QString operatorRef;//内部为组合操作符或自定义操作符
    bool isRef=false;//是否为自定义操作符
    bool isMakeOp=false;
    QString makeRef;//内部为Make操作符
    bool isFlattenOp=false;
    QString flattenRef;//内部为Flatten操作符
    parameter size;
    QStringList calls;//输入

    QString usedIdName;
    QString refName;
};

//PartialIterator
struct PartialIteratorOp
{
    QString partialIteratorType;//高阶类型
    QString operatorRef;//内部为组合操作符或自定义操作符
    bool isRef=false;//是否为自定义操作符
    bool isMakeOp=false;
    QString makeRef;//内部为Make操作符
    bool isFlattenOp=false;
    QString flattenRef;//内部为Flatten操作符
    parameter size;
    QString ifValue;
    bool hasDefault=false;
    QList<parameter> defaultValue;
    QStringList calls;//输入

    QString usedIdName;
    QString refName;
};

//用户自定义操作符
struct OpCall
{
    QString operatorRef;
    QStringList calls;
};

struct LineLength
{
    int hLength;
    int zLength;
};

struct Line
{
    QString leftIndex;
    QString rightIndex;

    QString leftEquationOid;
    QString rightEquationOid;

    int beginX;//连接线起点坐标
    int beginY;

    int endX;//连接线终点坐标
    int endY;
    int id;//图元ID
    QList<LineLength> lineLengthList;
};


//端口坐标
struct portCoordinate
{
    QString type;//端口类型
    QString paraValue;//当端口为参数端口，且参数为立即数时的值
    Line linkLine;//if、in、para端口的连接线
    int x;
    int y;
};

//被调用的含参数的操作符
struct opcallParaOperator
{
    parameter paraValue;//参数值
    QString operatorName;//操作符名
};

//逻辑里的图元
struct Equation
{
    QDomNode node;//等式节点

    QString oid;//图元oid
    QString redaceId;//生成的REDACEoid
    QString pageId;//图元所在图形页id

    QString type;//图元类型
    QString name;//图元名字
    QString comment;//图元注释

    QStringList lefts;//左值
    QString rightVarRef;//图元为变量或常量时的右值

    QString operatorType;//操作符种类
    QString operatorName;//操作符名字

    int id;//图元EleID

    QString opeName;
    QString eleType;
    QString text;
    QString immediateType;//图元为整数或浮点数立即数时对应的基础数据类型

    QList<portCoordinate> ifList;//if端口
    QList<portCoordinate> inList;//输入端口
    QList<portCoordinate> paraList;//参数端口
    QList<portCoordinate> outList;//输出端口

    QList<portCoordinate> rightList;//if、out、para列表
    //    QString ifNum;
    //    QString inNum;
    //    QString ParaNum;
    //    QString outNum;

    int x;
    int y;
    int width;
    int height;

    //    int linkId=10000;

    UnaryOp unaryOp;
    BinaryOp binaryOp;
    NAryOp nAryOp;
    PreOp preOp;
    InitOp initOp;
    FbyOp fbyOp;
    PrjOp prjOp;
    SliceOp sliceOp;
    PrjDynOp prjDynOp;
    DataStructOp dataStructOp;
    ScalarToVectorOp scalarToVectorOp;
    DataArrayOp dataArrayOp;
    ChgIthOp chgIthOp;
    IfThenElseOp ifThenElseOp;
    CaseOp caseOp;
    MakeOp makeOp;
    FlattenOp flattenOp;
    NumericCastOp numericCastOp;
    TimesOp timesOp;
    LslOp lslOp;
    LsrOp lsrOp;
    TransposeOp transposeOp;
    ActivateOp activateOp;
    RestartOp restartOp;
    IteratorOp iteratorOp;
    PartialIteratorOp partialIteratorOp;
    OpCall opCall;

    bool isLastVar=false;//是否为last变量

    bool isParaHigh=false;//是否为使用了参数的高阶操作符
    parameter paraValue;//参数的实例化的值

    bool isUnsupport=false;//是否为REDACE不支持的操作符
};

//图形页面
struct Diagram
{
    QString name;//名字
    QString oid;//oid
    QString redaceOid;//REDACEoid
    QString landscape;//landsacpe

    QList<Equation> equations;//图元
    QList<Line> lineList;//连接线

};

//被调用的含泛型操作符
struct opcallOperator
{
    Equation equation;
    QString operatorName;//操作符名
    QString opcallName;//被调用的操作符名
};

struct Transition;
struct StateMachine;
struct State;

struct RSM_DEFINED_EXPORT StateMachine {
    using Ptr = QSharedPointer<StateMachine>;
    QString         scadeOid;             //状态机oid
    QString         redaceOid;             //状态机oid
    QString         name;           //状态机名称
    QString         comment;        //状态机注释
    QString         projectid;      //工程id
    QString         poufilename;    //pou文件名
    QString         filename;       //语法文件名
    QString         projectpath;    // 工程路径
    QString         hierarchy;      //层级
    QString         initstate;      //初始状态
    QVector<QString>  statelist;    //状态列表
    QString         parentType;     //状态机的父节点类型Op/State
    QString         parentOid;      //状态机的父节点Oid
    QString         operatorOid;    //所属操作符oid
    bool            isSaved=true;   //是否被保存

    QRect           rect;



};

struct RSM_DEFINED_EXPORT POU {
    QString oid;
    QString name;
    QString filePath;

    Diagram dia;
};

struct RSM_DEFINED_EXPORT State{
    using Ptr = QSharedPointer<State>;
    QString         scadeOid;             //状态oid
    QString         redaceOid;             //状态oid
    QString         name;           //状态名
    QString         hierarchy;      //层级
    QString         comment;        //状态注释
    QString         parentid;       //所属状态机id
    QVector<QString>    stmList;    //状态机列表
    bool            isActive=false; //是否激活

    QVector<POU>    pouList;    //算法页列表
    bool            initial = false;
    bool            final = false;

    QVector<QString>  trans_strong;
    QVector<QString>  trans_weak;
    QVector<QString>  trans_sync;

    struct StateGE {
        QString present;
        QRect   rect;
    };

    StateGE     ge;

    QList<Variable> variables;//变量
    QList<Equation> equations;//逻辑

};

enum TransKind {
    STRONG,
    WEAK,
    SYNCHRO,
};

enum TransHistory {
    RESTART,
    RESUME,
};

struct RSM_DEFINED_EXPORT Transition{
    using Ptr =  QSharedPointer<Transition>;

    QString         oid;             //迁移oid
    QString         comment;        //注释
    QString         target;         //目标状态
    QString         source;         //起始状态
    TransKind       kind;           //迁移条件
    TransHistory    history;        //历史属性
    int             prior;          //优先级
    bool            isActive=false; //是否激活

    struct TransitionGE {
        QString present;
        QVector<QPoint> path; // start to end
    };

    TransitionGE    ge;

    QDomNode conditionNode;
    QList<QDomNode> actionNodes;

    // 设置和读取 condition, 自动进行 HTML 编码转换
    QString condition() const;
    void setCondition(const QString &condition);

    // 设置和读取 action, 自动进行 HTML 编码转换
    QString actions() const;
    void setActions(const QString &actions);

    // 读写 HTML 编码的 condition 和 action
    QString rawConditon() const { return condition_;}
    void setRawConditon(const QString & cond) { condition_ = cond;}

    QString rawAction() const { return actions_;}
    void setRawAction(const QString &act) { actions_ = act;}
//private:
    QString         condition_;  // html encoding, use getter & setter
    QString         actions_;  // html encoding
};

class StmModel
{
public:

    StmModel();

    void loadOperatorFile(const QString& projectOid,const QString& projectPath,const QString& operatorFileName);

    void addStateMachine(const QString& oid,const StateMachine &stm);
    void addState(const QString& oid,const State & state);
    void addTrans(const Transition& trans);

    StateMachine*  getStateMachine(const QString & oid = QString());
    State*  getState(const QString & oid);
    Transition*  getTransition(const QString & oid);

    void  deleteStateMachine(const QString & oid);
    void  deleteState(const QString & oid);
    void  deleteTransition(const QString & oid);

    QList<StateMachine*> getStateMachineList();
    QList<State*> getStateMachineStateList(const QString & oid);
    QList<Transition*> getStateTransitionList(const QString & oid);

    QList<QString> getPointedTransOfState(QString stateId);

    void updateAllTransPrior();

    // get stm id
    QString getSTMID(const StateMachine & stm);
    QString getSTMID(const State& state);
    QString getSTMID(const Transition& trans);

    /**
     * @brief getTransPriorList 获取迁移优先级列表
     * @param trans
     */
    QStringList getTransPriorList(const Transition& trans);

    const QMap<QString, StateMachine> & statemachines() const { return m_stms;}
    const QMap<QString, State> & states() const { return m_states;}
    const QMap<QString, Transition> & trans() const { return m_trans;}

    void setStms(QMap<QString,StateMachine> stms);
    void setStates(QMap<QString, State> states);
    void setTransitions(QMap<QString, Transition> trans);

    StateMachine saveSTMToPOU(const QString &stmid, const QString &filePath);

    void loadPOUXML(const QString & filePath);

    QString getOperatorName(const QString &operatorid, const QString &projectid);

    bool removeDirectory(const QString &dirPath);
private:

    void init();

    void writeTransitions(QXmlStreamWriter &stream, const QVector<QString> &transList, const QString &kind);
    void writeConditionOrActionBlock(QXmlStreamWriter &stream, const QString &blockName, const QRect &blockRect);


private:
    QMap<QString,StateMachine> m_stms;
    QMap<QString, State> m_states; //stateid, state
    QMap<QString, Transition> m_trans; //transid, trans

};

enum forkType{ACTION,IFNODE};
enum ifNodeType{THEN,ELSE,ROOT};

struct IfNodeFork
{
    forkType fork;
    QString oid;
};

struct IfBlock
{
    QString name;
    QString scadeOid;
    QString redaceOid;
    QString ifNodeOid;
};

struct IfNode
{
    QString condition;
    QDomNode conditionNode;
    ifNodeType type;
    QString scadeOid;
    QString redaceOid;
    IfNodeFork thenFork;
    IfNodeFork elseFork;
};

struct BlockAction
{
    ifNodeType type;
    QString scadeOid;
    QString redaceOid;
    QList<Variable> variables;//变量
    QList<Equation> equations;//逻辑
    QList<POU> pouList;
};

struct IfBlockModel
{
    QList<IfBlock> ifblockList;
    QMap<QString,IfNode> ifNodeMap;
    QMap<QString,BlockAction> actionMap;
};

//操作符
struct OperatorData
{
    QString operatorName;
    QString path;
    QString operatorFileName;
    QString projectOid;

    bool isImported=false;//是否是导入操作符
    bool hasPara=false;//是否包含参数
    bool hasT=false;//是否包含泛型
    QString cFilePath;

    QString scadeOid;//操作符oid
    QString redaceOid;
    QString comment;//操作符注释
    QString kind;//种类

    QString parameter;//参数

    bool isNew=false;//是否为参数实例化的操作符

    QList<opcallParaOperator> paraOperatorList;//操作符中调用的含参自定义操作符

    QList<opcallOperator> opCallList;//操作符中调用的自定义操作符

    QList<Variable> variables;//变量

    QList<Equation> equations;//逻辑

    QList<Diagram> diagrams;//页面

    QStringList logList;//导入日志

    QString projectPath;

    QStringList stmList;//顶层状态机Oid列表

    StmModel stmModel;

    IfBlockModel blockModel;

    int ifblockDiaNum=1;
};

#endif // OPERATORDEFINITION_H
